#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>

#include "distance.h"
#include "uart.h"

// Initialization
void distance_init(void)
{
  spi_master_init();
  adns_init();
}

void spi_master_init(void)
{
  // Setup Port B outputs
  // Everyone but MISO and OSCn are outputs
  DDRB = 0b00101111;
  // Set chip select high (inactive)
  PORTB |= (1<<ADNS_CS);
  // Enable SPI, Master, set clock rate fck/8
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);  
  SPSR = (1<<SPI2X);
  // Use MSB FIRST: DORD = 0
  
  // ADNS-3080 reads MOSI on rising edges of SCLK
  // Outputs MISO on falling edge SCLK
  // CPOL = 1, CPHA = 1
  SPCR |= (1<<CPOL) | (1<<CPHA);	
}

void adns_init(void)
{		
  //ADNS is ON
  PORTB |= (1<<ADNS_PD);
  // Reset must be raised and lowered (must be 10 us)
  PORTB |= (1<<ADNS_RESET);
  _delay_us(10);
  PORTB &= ~(1<<ADNS_RESET);
  // Wait a little
  _delay_us(100);
  //Disable serial port pull-ups
  spi_master_transmit(0x8b,0b00000100);  
}

char spi_master_transmit(unsigned char command, unsigned char byte)
{
  signed char input,junk;
  
  // Set CS to low to enable transmission
  PORTB &= ~(1<<ADNS_CS);
  // Start transmission
  SPDR = command;  //SPDR = SPI Data Register
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));
  _delay_us(10);
  junk = SPDR;  //receive junk that comes back
  _delay_us(75);
  SPDR = byte;
  while(!(SPSR & (1<<SPIF)));
  _delay_us(10);
  input = SPDR; 
  // Set CS to high at end of transmission
  PORTB |= (1<<ADNS_CS);
  //Return the data read from the second transmission
  return input;
}


char adns_chk_serial(void) 
{
  char ok=0;

  //Read Product_ID register
  adns_id = spi_master_transmit(0x00,0x00);
  _delay_us(50);
  //Read Inverse_Product_ID register
  adns_inv_id = spi_master_transmit(0x3f,0x00);
  ok |= ~(adns_id & adns_inv_id);
     
  return ok;
	
}

